#pragma once
#include <unordered_map>
#include <functional>
#include "TcpServer.hpp"
#include "Common.hpp"
#include "HttpProtocol.hpp"

namespace wxd
{
    class HttpServer : public nocopy
    {
        using httpserver_func_t = std::function<void(HttpRequest &, HttpResponse &)>;

    private:
        // 查找方法表，判断方法是否存在
        bool IsSafe(const std::string path) const
        {
            //LOG(LogLevel::DEBUG)<<(_func_route.find(path) != _func_route.end());
            return _func_route.find(path) != _func_route.end();
        }

        // Http服务器提供服务的方法，用于传给TcpServer，因为创建多进程/线程的TcpServer
        // 所以必须由TcpServer执行任务
        bool Service(std::shared_ptr<Socket> socket_ptr, const InetAddrTrans &client)
        {
            // LOG(LogLevel::DEBUG) << "成功回调HttpServer Service方法";
            // 接收报文-在这里，先认为读到的是完整的报文
            std::string read_str;
            socket_ptr->Recv(read_str);
            LOG(LogLevel::DEBUG) << "收到报文：" << read_str;
            // 解析报文
            HttpRequest request;
            request.Deserialize(read_str);
            request.PrintDebug();

            // 如果是静态请求，直接让HttpResonse自动构建
            // 如果是动态请求，让外部的方法构建HttpResonse
            HttpResponse response;

            // 判断是否需要执行方法 并且 方法键值是否存在
            // LOG(LogLevel::DEBUG) << request.IsExe();
            // LOG(LogLevel::DEBUG) << request.FuncPath();
            // LOG(LogLevel::DEBUG) << request.FuncArgs();

            if (request.IsExe() && IsSafe(request.FuncPath()))
            {
                LOG(LogLevel::DEBUG) << "safe";
                // 存在-从方法中获取response
                _func_route[request.FuncPath()](request, response);
            }

            else
                // 不需要执行方法-自动构建response
                response.Build(request);
            std::string response_str;
            response.Serialize(response_str);
            // 发送报文
            socket_ptr->Send(response_str);
            return true;
        }

    public:
        HttpServer(u_int16_t port)
            : _port(port), _tcp_server_ptr(std::make_unique<TcpServer>(_port))
        {
        }
        void Start()
        {
            _tcp_server_ptr->Init();
            // 把方法传给TcpServer-lambda
            _tcp_server_ptr->FuncInit([this](std::shared_ptr<Socket> socket_ptr, const InetAddrTrans &client)
                                      { return this->Service(socket_ptr, client); });
            // auto task = std::bind(&Service,this,std::placeholders::_1,std::placeholders::_2);

            // 启动TcpServer
            _tcp_server_ptr->Start();
        }
        void Register(const std::string &func_path, httpserver_func_t func) // 用于外部注册方法
        {
            _func_route.emplace(func_path, func);
        }

    private:
        u_int16_t _port;
        std::unique_ptr<TcpServer> _tcp_server_ptr;
        std::unordered_map<std::string, httpserver_func_t> _func_route; // http服务器方法路由
    };
}
